package com.fgsort;

import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.event.EventListenerList;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
 
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.swing.JComboBox;
import javax.swing.DefaultComboBoxModel;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;

public class PanelFgSort extends JPanel {
	private static final long serialVersionUID = 1L;

	private EventListenerList listenerList = new EventListenerList();
	JButton btnSort = new JButton("Sort");
	JButton btnExitApp = new JButton("Exit");
	private final JTextField txtStatus = new JTextField(10);

	public String sUnsortedFile = null; 
	public String sFgXmlFile = "c:/Program Files/iTool/FgStdListAll.xml"; 
	
	private final JLabel lblFuncGrpSort = new JLabel("Function Group Sort");
	private final JSeparator separator = new JSeparator();
	private final JSeparator separator_1 = new JSeparator();
	private final JSeparator separator_4 = new JSeparator();

	public boolean bTestSelected = true;
	private final JTextField txtExcelFile = new JTextField("");
	private final JLabel lblFilename = new JLabel("Unsorted Function Group file");
	private final JButton btnSelectUnsortedFile = new JButton("Select");
	private final JTextField txtUnsortedFile = new JTextField("c:/Program Files/iTool/");
	private final JLabel lblConfiguration = new JLabel("Configuration");
	private final JButton btnXmlSelect = new JButton("Select");
	private final JTextField txtFgXmlLoc = new JTextField("C:/Program Files/iTool/FgStdList.xml");
	private final JTextField txtXlsDirLoc = new JTextField("Select the location to save .xls file");
	private final JButton btnXlsDirSelect = new JButton("Select");
	private final JComboBox cboxPlcQty = new JComboBox();
	private final JSeparator separator_2 = new JSeparator();
	private final JTextField txtPlc1StnNo = new JTextField();
	private final JTextField txtPlc2StnNo = new JTextField();
	private final JTextField txtPlc3StnNo = new JTextField();
	private final JTextField txtPlc4StnNo = new JTextField();
	private final JLabel lblPlc1StnNo = new JLabel("PLC1");
	private final JLabel lblPlc2StnNo = new JLabel("PLC2");
	private final JLabel lblPlc3StnNo = new JLabel("PLC3");
	private final JLabel lblPlc4StnNo = new JLabel("PLC4");
	private final JLabel lblQty = new JLabel("QTY");
	private final JLabel lblPlcQty = new JLabel("PLC Option");
	private final JSeparator separator_5 = new JSeparator();
	private final JSeparator separator_6 = new JSeparator();

	int iPlcQty = 0;
	
	public PanelFgSort(String sPanelTitle) {	
		
		GridBagLayout gridBagLayout = new GridBagLayout();
		gridBagLayout.columnWidths = new int[]{32, 0, 0, 0, 0, 33, 75};
		gridBagLayout.rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 28, -110, 0};
		gridBagLayout.columnWeights = new double[]{0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0};
		gridBagLayout.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE};
		setLayout(gridBagLayout);
		
		setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.gray), sPanelTitle));
		
		GridBagConstraints gbc_separator_4 = new GridBagConstraints();
		gbc_separator_4.gridwidth = 7;
		gbc_separator_4.fill = GridBagConstraints.BOTH;
		gbc_separator_4.insets = new Insets(0, 0, 5, 0);
		gbc_separator_4.gridx = 0;
		gbc_separator_4.gridy = 0;
		separator_4.setForeground(new Color(119, 136, 153));
		add(separator_4, gbc_separator_4);
		
		GridBagConstraints gbc_lblFuncGrpSort = new GridBagConstraints();
		gbc_lblFuncGrpSort.gridwidth = 7;
		gbc_lblFuncGrpSort.insets = new Insets(0, 0, 5, 0);
		gbc_lblFuncGrpSort.gridx = 0;
		gbc_lblFuncGrpSort.gridy = 1;
		lblFuncGrpSort.setForeground(Color.BLACK);
		lblFuncGrpSort.setFont(new Font("Tahoma", Font.BOLD, 13));
		add(lblFuncGrpSort, gbc_lblFuncGrpSort);
		
		GridBagConstraints gbc_separator_1 = new GridBagConstraints();
		gbc_separator_1.fill = GridBagConstraints.BOTH;
		gbc_separator_1.gridwidth = 7;
		gbc_separator_1.insets = new Insets(0, 0, 5, 0);
		gbc_separator_1.gridx = 0;
		gbc_separator_1.gridy = 2;
		separator_1.setForeground(new Color(119, 136, 153));
		add(separator_1, gbc_separator_1);
		
		GridBagConstraints gbc_separator_5 = new GridBagConstraints();
		gbc_separator_5.fill = GridBagConstraints.BOTH;
		gbc_separator_5.gridwidth = 7;
		gbc_separator_5.insets = new Insets(0, 0, 5, 0);
		gbc_separator_5.gridx = 0;
		gbc_separator_5.gridy = 7;
		separator_5.setForeground(new Color(119, 136, 153));
		add(separator_5, gbc_separator_5);
		
		GridBagConstraints gbc_separator_6 = new GridBagConstraints();
		gbc_separator_6.fill = GridBagConstraints.BOTH;
		gbc_separator_6.gridwidth = 7;
		gbc_separator_6.insets = new Insets(0, 0, 5, 0);
		gbc_separator_6.gridx = 0;
		gbc_separator_6.gridy = 9;
		separator_6.setForeground(new Color(119, 136, 153));
		add(separator_6, gbc_separator_6);
		
		GridBagConstraints gbc_lblPlcQty = new GridBagConstraints();
		gbc_lblPlcQty.anchor = GridBagConstraints.WEST;
		gbc_lblPlcQty.gridwidth = 6;
		gbc_lblPlcQty.insets = new Insets(0, 0, 5, 5);
		gbc_lblPlcQty.gridx = 0;
		gbc_lblPlcQty.gridy = 8;
		lblPlcQty.setForeground(Color.DARK_GRAY);
		lblPlcQty.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblPlcQty, gbc_lblPlcQty);
		
		GridBagConstraints gbc_lblQty = new GridBagConstraints();
		gbc_lblQty.insets = new Insets(0, 0, 5, 5);
		gbc_lblQty.gridx = 0;
		gbc_lblQty.gridy = 10;
		lblQty.setForeground(Color.DARK_GRAY);
		lblQty.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblQty, gbc_lblQty);
		
		cboxPlcQty.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				iPlcQty = cboxPlcQty.getSelectedIndex();
				switch (iPlcQty) {
				
				case 0: 
					txtPlc1StnNo.setEnabled(false);
					txtPlc2StnNo.setEnabled(false);
					txtPlc3StnNo.setEnabled(false);
					txtPlc4StnNo.setEnabled(false);
					break;

				case 1:
					txtPlc1StnNo.setEnabled(true);
					txtPlc2StnNo.setEnabled(false);
					txtPlc3StnNo.setEnabled(false);
					txtPlc4StnNo.setEnabled(false);
					break;

				case 2:
					txtPlc1StnNo.setEnabled(true);
					txtPlc2StnNo.setEnabled(true);
					txtPlc3StnNo.setEnabled(false);
					txtPlc4StnNo.setEnabled(false);
					break;

				case 3:
					txtPlc1StnNo.setEnabled(true);
					txtPlc2StnNo.setEnabled(true);
					txtPlc3StnNo.setEnabled(true);
					txtPlc4StnNo.setEnabled(false);
					break;

				case 4:
					txtPlc1StnNo.setEnabled(true);
					txtPlc2StnNo.setEnabled(true);
					txtPlc3StnNo.setEnabled(true);
					txtPlc4StnNo.setEnabled(true);
					break;

					
				}
				//OptionPane.showMessageDialog(OptionPanel.this, iPlcQty,"Information",JOptionPane.ERROR_MESSAGE);
			}
		});
		
		GridBagConstraints gbc_lblPlc1StnNo = new GridBagConstraints();
		gbc_lblPlc1StnNo.insets = new Insets(0, 0, 5, 5);
		gbc_lblPlc1StnNo.gridx = 1;
		gbc_lblPlc1StnNo.gridy = 10;
		lblPlc1StnNo.setForeground(Color.DARK_GRAY);
		lblPlc1StnNo.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblPlc1StnNo, gbc_lblPlc1StnNo);
		
		GridBagConstraints gbc_lblPlc2StnNo = new GridBagConstraints();
		gbc_lblPlc2StnNo.insets = new Insets(0, 0, 5, 5);
		gbc_lblPlc2StnNo.gridx = 2;
		gbc_lblPlc2StnNo.gridy = 10;
		lblPlc2StnNo.setForeground(Color.DARK_GRAY);
		lblPlc2StnNo.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblPlc2StnNo, gbc_lblPlc2StnNo);
		
		GridBagConstraints gbc_lblPlc3StnNo = new GridBagConstraints();
		gbc_lblPlc3StnNo.insets = new Insets(0, 0, 5, 5);
		gbc_lblPlc3StnNo.gridx = 3;
		gbc_lblPlc3StnNo.gridy = 10;
		lblPlc3StnNo.setForeground(Color.DARK_GRAY);
		lblPlc3StnNo.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblPlc3StnNo, gbc_lblPlc3StnNo);
		
		GridBagConstraints gbc_lblPlc4StnNo = new GridBagConstraints();
		gbc_lblPlc4StnNo.insets = new Insets(0, 0, 5, 5);
		gbc_lblPlc4StnNo.gridx = 4;
		gbc_lblPlc4StnNo.gridy = 10;
		lblPlc4StnNo.setForeground(Color.DARK_GRAY);
		lblPlc4StnNo.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblPlc4StnNo, gbc_lblPlc4StnNo);
		
		GridBagConstraints gbc_cboxPlcQty = new GridBagConstraints();
		gbc_cboxPlcQty.anchor = GridBagConstraints.WEST;
		gbc_cboxPlcQty.insets = new Insets(0, 0, 5, 5);
		gbc_cboxPlcQty.gridx = 0;
		gbc_cboxPlcQty.gridy = 11;
		
		cboxPlcQty.setToolTipText("select the number of plc's in the plant area. \r\n* = export all function groups into 1 tab\r\n");
		cboxPlcQty.setModel(new DefaultComboBoxModel(new String[] {"*", "1", "2", "3", "4"}));
		cboxPlcQty.setMaximumRowCount(5);
		add(cboxPlcQty, gbc_cboxPlcQty);
		
		GridBagConstraints gbc_txtPlc1StnNo = new GridBagConstraints();
		gbc_txtPlc1StnNo.insets = new Insets(0, 0, 5, 5);
		gbc_txtPlc1StnNo.fill = GridBagConstraints.BOTH;
		gbc_txtPlc1StnNo.gridx = 1;
		gbc_txtPlc1StnNo.gridy = 11;
		txtPlc1StnNo.setToolTipText("1 = export all FG into 1 tab (define last station of plc1 area)");
		txtPlc1StnNo.setEnabled(false);
		txtPlc1StnNo.setHorizontalAlignment(JTextField.CENTER);
		add(txtPlc1StnNo, gbc_txtPlc1StnNo);
		
		GridBagConstraints gbc_txtPlc2StnNo = new GridBagConstraints();
		gbc_txtPlc2StnNo.insets = new Insets(0, 0, 5, 5);
		gbc_txtPlc2StnNo.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtPlc2StnNo.gridx = 2;
		gbc_txtPlc2StnNo.gridy = 11;
		txtPlc2StnNo.setToolTipText("2 = export plc1 + plc2  FG into 2 tabs (define last station of each plc area)\r\n");
		txtPlc2StnNo.setEnabled(false);
		txtPlc2StnNo.setHorizontalAlignment(JTextField.CENTER);
		add(txtPlc2StnNo, gbc_txtPlc2StnNo);
		
		GridBagConstraints gbc_txtPlc3StnNo = new GridBagConstraints();
		gbc_txtPlc3StnNo.insets = new Insets(0, 0, 5, 5);
		gbc_txtPlc3StnNo.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtPlc3StnNo.gridx = 3;
		gbc_txtPlc3StnNo.gridy = 11;
		txtPlc3StnNo.setToolTipText("3 = export plc1 + plc2 + plc3  FG into 3 tabs (define last station of each plc area)");
		txtPlc3StnNo.setEnabled(false);
		txtPlc3StnNo.setHorizontalAlignment(JTextField.CENTER);
		add(txtPlc3StnNo, gbc_txtPlc3StnNo);
		
		GridBagConstraints gbc_txtPlc4StnNo = new GridBagConstraints();
		gbc_txtPlc4StnNo.insets = new Insets(0, 0, 5, 5);
		gbc_txtPlc4StnNo.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtPlc4StnNo.gridx = 4;
		gbc_txtPlc4StnNo.gridy = 11;
		txtPlc4StnNo.setToolTipText("4 = export plc1 + plc2 + plc3 + plc4  FG into 4 tabs (define last station of each plc area)");
		txtPlc4StnNo.setEnabled(false);
		txtPlc4StnNo.setHorizontalAlignment(JTextField.CENTER);
		add(txtPlc4StnNo, gbc_txtPlc4StnNo);
		
		GridBagConstraints gbc_separator_2 = new GridBagConstraints();
		gbc_separator_2.fill = GridBagConstraints.BOTH;
		gbc_separator_2.gridwidth = 7;
		gbc_separator_2.insets = new Insets(0, 0, 5, 0);
		gbc_separator_2.gridx = 0;
		gbc_separator_2.gridy = 13;
		separator_2.setForeground(new Color(119, 136, 153));
		add(separator_2, gbc_separator_2);
		
		GridBagConstraints gbc_lblFilename = new GridBagConstraints();
		gbc_lblFilename.gridwidth = 6;
		gbc_lblFilename.anchor = GridBagConstraints.WEST;
		gbc_lblFilename.insets = new Insets(0, 0, 5, 5);
		gbc_lblFilename.gridx = 0;
		gbc_lblFilename.gridy = 3;
		lblFilename.setForeground(Color.DARK_GRAY);
		lblFilename.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblFilename, gbc_lblFilename);
		
		GridBagConstraints sepGmail = new GridBagConstraints();
		sepGmail.gridwidth = 7;
		sepGmail.fill = GridBagConstraints.BOTH;
		sepGmail.insets = new Insets(0, 0, 5, 0);
		sepGmail.gridx = 0;
		sepGmail.gridy = 4;
		separator.setForeground(new Color(119, 136, 153));
		add(separator, sepGmail);
		txtUnsortedFile.setEditable(false);
		txtUnsortedFile.setColumns(10);
		
		GridBagConstraints gbc_txtUnsortedFile = new GridBagConstraints();
		gbc_txtUnsortedFile.gridwidth = 6;
		gbc_txtUnsortedFile.insets = new Insets(0, 0, 5, 5);
		gbc_txtUnsortedFile.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtUnsortedFile.gridx = 0;
		gbc_txtUnsortedFile.gridy = 5;
		add(txtUnsortedFile, gbc_txtUnsortedFile);
		
		GridBagConstraints gbc_btnSelectUnsortedFile = new GridBagConstraints();
		gbc_btnSelectUnsortedFile.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnSelectUnsortedFile.insets = new Insets(0, 0, 5, 0);
		gbc_btnSelectUnsortedFile.gridx = 6;
		gbc_btnSelectUnsortedFile.gridy = 5;
		btnSelectUnsortedFile.setToolTipText("select the .txt file that contains the unsorted function groups");
		btnSelectUnsortedFile.setFont(new Font("Tahoma", Font.PLAIN, 13));
		add(btnSelectUnsortedFile, gbc_btnSelectUnsortedFile);

		GridBagConstraints gbc_txtExcelFile = new GridBagConstraints();
		gbc_txtExcelFile.gridwidth = 6;
		gbc_txtExcelFile.insets = new Insets(0, 0, 5, 5);
		gbc_txtExcelFile.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtExcelFile.gridx = 0;
		gbc_txtExcelFile.gridy = 6;
		add(txtExcelFile, gbc_txtExcelFile);
		
		btnSort.setToolTipText("press here to sort function groups and generate excel file");
		btnSort.setFont(new Font("Tahoma", Font.PLAIN, 13));
		GridBagConstraints gbc_btnSort = new GridBagConstraints();
		gbc_btnSort.fill = GridBagConstraints.BOTH;
		gbc_btnSort.insets = new Insets(0, 0, 5, 0);
		gbc_btnSort.gridx = 6;
		gbc_btnSort.gridy = 6;
		add(btnSort, gbc_btnSort);
		
		///button - select unsorted function group file
		btnSelectUnsortedFile.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		sUnsortedFile = chooseFile(txtUnsortedFile.getText());
        		txtUnsortedFile.setText(sUnsortedFile);
        		txtExcelFile.setText(stripExtension(sUnsortedFile)+".xls");
        		}
        	}
        );
		txtExcelFile.setEditable(false);
		txtExcelFile.setColumns(10);
		
		///button - select unsorted function group file
		btnXmlSelect.addActionListener(new ActionListener() {
        	public void actionPerformed(ActionEvent e) {
        		sFgXmlFile = chooseFile("c://Program Files/iTool/");
        		txtFgXmlLoc.setText(sFgXmlFile);
        		}
        	}
        );
		
	
		///button sort
	    btnSort.addActionListener(new ActionListener() {

	    	public void actionPerformed(ActionEvent e) {
	      
	        if (sUnsortedFile != null)	{	
	        	try {
        			///if sorting by plc is required 
    				List<String> lstPlcStn = new ArrayList<String>();
    				
        				switch(iPlcQty) {
        					case 0:
        						lstPlcStn.add("000");
        						lstPlcStn.add("999");
        						break;
        					case 1:
        						lstPlcStn.add("000");
        						lstPlcStn.add(txtPlc1StnNo.getText());
        						break;
        					case 2:
        						lstPlcStn.add("000");
        						lstPlcStn.add(txtPlc1StnNo.getText());
        						lstPlcStn.add(txtPlc2StnNo.getText());
        						break;
        					case 3:
        						lstPlcStn.add("000");
        						lstPlcStn.add(txtPlc1StnNo.getText());
        						lstPlcStn.add(txtPlc2StnNo.getText());
        						lstPlcStn.add(txtPlc3StnNo.getText());
        						break;
        					case 4:
        						lstPlcStn.add("000");
        						lstPlcStn.add(txtPlc1StnNo.getText());
        						lstPlcStn.add(txtPlc2StnNo.getText());
        						lstPlcStn.add(txtPlc3StnNo.getText());
        						lstPlcStn.add(txtPlc4StnNo.getText());
        						break;
        					default:
        				}

	        		///get all standard FG's defined in XML list 
	        		List<String> lstFunctionGroupsXmlNames = new ArrayList<String>();
	        		lstFunctionGroupsXmlNames.addAll(getFunctionGroupXmlNames(sFgXmlFile));
	        		
	        		List<List<List<String>>> lstFunctionGroupsSheet = new ArrayList<List<List<String>>>();
	
	        		for(int nCntFgSheet = 0; nCntFgSheet < lstPlcStn.size()-1; nCntFgSheet++) {
		        		
	        			List<List<String>> lstFunctionGroupsTable = new ArrayList<List<String>>();
		        		
	        			for(int nCntXmlNames = 0; nCntXmlNames < lstFunctionGroupsXmlNames.size(); nCntXmlNames++) {
		            		List<String> lstFunctionGroupsFound = new ArrayList<String>();
		            		if(!getFuncGrpList(lstFunctionGroupsXmlNames.get(nCntXmlNames)).isEmpty())	{
			            		///function group column title
		            			lstFunctionGroupsFound.add(lstFunctionGroupsXmlNames.get(nCntXmlNames));
		            			
	            				lstFunctionGroupsFound.addAll(getFuncGrpList(lstFunctionGroupsXmlNames.get(nCntXmlNames), lstPlcStn.get(nCntFgSheet), lstPlcStn.get(nCntFgSheet+1)));
		                		///add found column to function group table
		                		lstFunctionGroupsTable.add(lstFunctionGroupsFound);
	
		                		for (int i = 0; i < lstFunctionGroupsTable.size(); i++) {
		    	                	fireOptionEvent(new OptionEvent(this, lstFunctionGroupsTable.get(i).toString()));
		    	                	//System.out.println(lstFunctionGroupsTable.get(i));
		    	                }
		    	        		
//		    	                for (int i = 0; i < lstFunctionGroupsTable.get(0).size(); i++) {
//		    	                	fireOptionEvent(new OptionEvent(this, lstFunctionGroupsTable.get(0).get(i).toString()));
//		    	                	//System.out.println(lstFunctionGroupsTable.get(0).get(i));
//		    	                }
		    	                
	            				//lstFunctionGroupsFound.addAll(getFuncGrpList(lstFunctionGroupsXmlNames.get(nCntXmlNames)));
		    	                //lstFunctionGroupsTable.add(lstFunctionGroupsFound);
	
		            		}
		        		}
//        				System.out.print(lstPlcStn.get(nCntFgSheet));
//        				System.out.print(" ");
//        				System.out.println(lstPlcStn.get(nCntFgSheet+1));
        				
		        		lstFunctionGroupsSheet.add(lstFunctionGroupsTable);
	        		}
	        		
	        		ExcelWriteListFile ewf = new ExcelWriteListFile();
	                ewf.ExcelWriteListToFile(lstFunctionGroupsSheet, txtExcelFile.getText());
	                
	        		} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (ParserConfigurationException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (SAXException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
	        		  catch (NullPointerException ex) {
	        			  System.out.println("null pointer returned for function group names! [getFunctionGroupXmlNames()]");
	        		}
	        		
		            }
		            else {
		            	JOptionPane.showMessageDialog(PanelFgSort.this,"Select an unsorted Function Group .txt file ","Information",JOptionPane.ERROR_MESSAGE);
		            }
	        	}
			}
	    );
	    
	    ///call error checking method for plc station numbers
	    PlcStnNoErrChk();
		
		GridBagConstraints gbc_lblConfiguration = new GridBagConstraints();
		gbc_lblConfiguration.anchor = GridBagConstraints.WEST;
		gbc_lblConfiguration.gridwidth = 6;
		gbc_lblConfiguration.insets = new Insets(0, 0, 5, 5);
		gbc_lblConfiguration.gridx = 0;
		gbc_lblConfiguration.gridy = 14;
		lblConfiguration.setForeground(Color.DARK_GRAY);
		lblConfiguration.setFont(new Font("Tahoma", Font.BOLD, 11));
		add(lblConfiguration, gbc_lblConfiguration);
		
		GridBagConstraints gbc_txtFgXmlLoc = new GridBagConstraints();
		gbc_txtFgXmlLoc.gridwidth = 6;
		gbc_txtFgXmlLoc.insets = new Insets(0, 0, 5, 5);
		gbc_txtFgXmlLoc.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtFgXmlLoc.gridx = 0;
		gbc_txtFgXmlLoc.gridy = 15;
		txtFgXmlLoc.setEditable(false);
		txtFgXmlLoc.setToolTipText("Select the FG .xml file location");
		txtFgXmlLoc.setColumns(10);
		add(txtFgXmlLoc, gbc_txtFgXmlLoc);
		
		GridBagConstraints gbc_btnXmlSelect = new GridBagConstraints();
		gbc_btnXmlSelect.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnXmlSelect.insets = new Insets(0, 0, 5, 0);
		gbc_btnXmlSelect.gridx = 6;
		gbc_btnXmlSelect.gridy = 15;
		btnXmlSelect.setToolTipText("Select the FG .xml file location");
		btnXmlSelect.setFont(new Font("Tahoma", Font.PLAIN, 13));
		add(btnXmlSelect, gbc_btnXmlSelect);
		
		GridBagConstraints gbc_txtXlsDirLoc = new GridBagConstraints();
		gbc_txtXlsDirLoc.gridwidth = 6;
		gbc_txtXlsDirLoc.insets = new Insets(0, 0, 5, 5);
		gbc_txtXlsDirLoc.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtXlsDirLoc.gridx = 0;
		gbc_txtXlsDirLoc.gridy = 16;
		txtXlsDirLoc.setEditable(false);
		txtXlsDirLoc.setToolTipText("Select the location to save .xls file");
		txtXlsDirLoc.setColumns(10);
		add(txtXlsDirLoc, gbc_txtXlsDirLoc);
		
		GridBagConstraints gbc_btnXlsDirSelect = new GridBagConstraints();
		gbc_btnXlsDirSelect.fill = GridBagConstraints.HORIZONTAL;
		gbc_btnXlsDirSelect.insets = new Insets(0, 0, 5, 0);
		gbc_btnXlsDirSelect.gridx = 6;
		gbc_btnXlsDirSelect.gridy = 16;
		btnXlsDirSelect.setEnabled(false);
		btnXlsDirSelect.setToolTipText("Select the location to save .xls file");
		btnXlsDirSelect.setFont(new Font("Tahoma", Font.PLAIN, 13));
		add(btnXlsDirSelect, gbc_btnXlsDirSelect);
		
		btnExitApp.setFont(new Font("Tahoma", Font.BOLD, 13));
		GridBagConstraints gbc_btnExitApp = new GridBagConstraints();
		gbc_btnExitApp.fill = GridBagConstraints.BOTH;
		gbc_btnExitApp.gridwidth = 7;
		gbc_btnExitApp.insets = new Insets(0, 0, 5, 0);
		gbc_btnExitApp.gridx = 0;
		gbc_btnExitApp.gridy = 18;
		add(btnExitApp, gbc_btnExitApp);

		txtStatus.setText("status");
		txtStatus.setEditable(false);
		GridBagConstraints gbc_txtStatus = new GridBagConstraints();
		gbc_txtStatus.anchor = GridBagConstraints.NORTH;
		gbc_txtStatus.gridwidth = 7;
		gbc_txtStatus.fill = GridBagConstraints.HORIZONTAL;
		gbc_txtStatus.gridx = 0;
		gbc_txtStatus.gridy = 19;
		add(txtStatus, gbc_txtStatus);
		txtStatus.setColumns(10);
        
	///exit button
    btnExitApp.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
        	exitApp();
            	}
        	}
        );
       
	}
	
	//enum PlcSelect {ALL, PLC1, PLC2, PLC3, PLC4};
	
    public void fireOptionEvent(OptionEvent event) {
        Object[] listeners = listenerList.getListenerList();
         
        for(int i=0; i < listeners.length; i += 2) {
            if(listeners[i] == OptionListener.class) {
                ((OptionListener)listeners[i+1]).detailEventOccurred(event);
            }
        }
    }
    
    public void addOptionListener(OptionListener listener) {
        listenerList.add(OptionListener.class, listener);
    }
    
	private void exitApp() {
		System.exit(0);
	}

	///search function group in array (from file fg list)
    public List<String> getFuncGrpList(String sFunctionGroupName) throws IOException {

    	List<String> aFuncGrpValid = new ArrayList<String>();
    	//List<String> aFuncGrpInValid = new ArrayList<String>();
    	
    	FileArrayProvider fap = new FileArrayProvider();
    	//String[] lines = fap.readLines("d:/tmp/FunctionGroups/AS21M11_FG.txt");
    	String[] lines = fap.readLines(sUnsortedFile);

    	String sFg;
    	
    	///finds valid function groups and stores in array
        for (String line : lines) {
        	sFg = "";
        	line = line.trim();
        	if (line.length() > 8) {	///check minimum function group string length
	        	if (line.contains(sFunctionGroupName)) {
	        		sFg = line.substring(line.indexOf(sFunctionGroupName) - 3, line.indexOf(sFunctionGroupName) + 6);
        			aFuncGrpValid.add(sFg);
	        	}
    		}
		}

        ///create a HashSet which allows no duplicates
        HashSet<String> hashSet = new HashSet<String>(aFuncGrpValid);

        ///assign the HashSet to a new ArrayList
        ArrayList<String> lstFg = new ArrayList<String>(hashSet);
        
        ///sort list in ascending order
        Collections.sort(lstFg);

        return lstFg;
    }
        
	///search function group in array (from file fg list) by station number
    public List<String> getFuncGrpList(String sFunctionGroupName, String sStartStnNo, String sEndStnNo) throws IOException {

    	int iStartStnNo = Integer.parseInt(sStartStnNo);
    	int iEndStnNo = Integer.parseInt(sEndStnNo);
    	
    	List<String> aFuncGrpValid = new ArrayList<String>();
    	
    	FileArrayProvider fap = new FileArrayProvider();
    	
    	String[] lines = fap.readLines(sUnsortedFile);

    	String sFg;
    	
    	///finds valid function groups and stores in array
        for (String line : lines) {
        	sFg = "";
        	line = line.trim();
        	if (line.length() > 8) {	///check minimum function group string length
	        	if (line.contains(sFunctionGroupName)) {
		        	sFg = line.substring(line.indexOf(sFunctionGroupName) - 3, line.indexOf(sFunctionGroupName) + 6);
		        	//System.out.println(sFg.substring(0,3));
		        	if (isNumeric(sFg.substring(0,3)) == true) {
			        	if (Integer.parseInt(sFg.substring(0,3)) >= iStartStnNo && Integer.parseInt(sFg.substring(0,3)) <= iEndStnNo)	{
			        			aFuncGrpValid.add(sFg);
			        	}
		        	}
	        	}
    		}
		}

        ///create a HashSet which allows no duplicates
        HashSet<String> hashSet = new HashSet<String>(aFuncGrpValid);

        ///assign the HashSet to a new ArrayList
        ArrayList<String> lstFg = new ArrayList<String>(hashSet) ;
        
        ///sort list in ascending order
        Collections.sort(lstFg);

        return lstFg;
    }

    ///check if string is a number value
    public static boolean isNumeric(String str)  
    {  
      try  
      {  
        int i = Integer.parseInt(str);  
      }  
      catch(NumberFormatException nfe)  
      {  
        return false;  
      }  
      return true;  
    }
    
    
///xml parser - get the 'description' of a function group
//    public void getFuncGrpDesc(String fileName) throws IOException, ParserConfigurationException, SAXException {
//    	String  sNodeListName;
//    		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//            DocumentBuilder db = dbf.newDocumentBuilder();
//            File file = new File(fileName);
//            if (file.exists()) {
//
//            	Document doc = db.parse(file);
//                Element docEle = doc.getDocumentElement();
// 
//                ///print root element of the document
//                //System.out.println("Root element of the document: " + docEle.getNodeName());
// 
//                NodeList FunctionGroupList = docEle.getElementsByTagName("functiongroup");
// 
//                ///print total student elements in document
//                //System.out.println("Total function groups: " + FunctionGroupList.getLength());
// 
//           
//                if (FunctionGroupList != null && FunctionGroupList.getLength() > 0) {
//                    for (int i = 0; i < FunctionGroupList.getLength(); i++) {
// 
//                        Node node = FunctionGroupList.item(i);
// 
//                        if (node.getNodeType() == Node.ELEMENT_NODE) {
// 
//                            Element e = (Element) node;
//                            NodeList nodeListName = e.getElementsByTagName("name");
//                            sNodeListName = nodeListName.item(0).getChildNodes().item(0).getNodeValue().trim();
//                            if (sNodeListName.equals(txtFuncGrp.getText())) {
//                            	NodeList nodeListDesc = e.getElementsByTagName("description");
//                            	fireOptionEvent(new OptionEvent(this, nodeListDesc.item(0).getChildNodes().item(0).getNodeValue()));
//                            	//System.out.println("Description:" + nodeListDesc.item(0).getChildNodes().item(0).getNodeValue());
//                            }
//
// 
//                        }
//                    }
//                }
//            }
//            else {
//            	fireOptionEvent(new OptionEvent(this, "file does not exist!"));
//            }
//            	
//    }

    ///xml parser - get all the elements under 'name' of all function groups 
    public ArrayList<String> getFunctionGroupXmlNames(String fileName) throws IOException, ParserConfigurationException, SAXException {
    		
    		String  sNodeListName;
    		//String[] aFuncGrpNames = null;
    		ArrayList<String> aFuncGrpNames = new ArrayList<String>();
    		
    		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            File file = new File(fileName);
            if (file.exists()) {

            	Document doc = db.parse(file);
                Element docEle = doc.getDocumentElement();
                NodeList FunctionGroupList = docEle.getElementsByTagName("functiongroup");
         		//aFuncGrpNames = new String[FunctionGroupList.getLength()];
           
                if (FunctionGroupList != null && FunctionGroupList.getLength() > 0) {
                    for (int i = 0; i < FunctionGroupList.getLength(); i++) {
                         Node node = FunctionGroupList.item(i);
                         if (node.getNodeType() == Node.ELEMENT_NODE) {
                            Element e = (Element) node;
                            NodeList nodeListName = e.getElementsByTagName("name");
                            sNodeListName = nodeListName.item(0).getChildNodes().item(0).getNodeValue().trim();
                            aFuncGrpNames.add(sNodeListName);
                        }
                    }
                }
            }
            else {
            	fireOptionEvent(new OptionEvent(this, "file does not exist!"));
            }
            
			return aFuncGrpNames;
    }
    
    ///check if any of the xml function groups exist in line
    public boolean isFunctionGroup(String[] aFunctionGroupNames, String sLineFromFile) {
    	
	    for(int i =0; i < aFunctionGroupNames.length; i++)
	    {
	        if(sLineFromFile.contains(aFunctionGroupNames[i]))
	        {
	            return true;
	        }
	    }
	    return false;
    }
    
	private String chooseFile(String sFileLocation) {

		 String sfileName = null;
		  
		  //JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
		 JFileChooser chooser = new JFileChooser(sFileLocation);
	      int option = chooser.showOpenDialog(PanelFgSort.this);
	      if(option == JFileChooser.APPROVE_OPTION) {
	    	  txtStatus.setText("You chose "+((chooser.getSelectedFile()!=null)? chooser.getSelectedFile().getAbsoluteFile():"nothing"));
	    	  sfileName = chooser.getSelectedFile().getAbsoluteFile().toString();
	      }
	      if(option == JFileChooser.CANCEL_OPTION) {
	    	  txtStatus.setText("You canceled.");
	       }
		  return sfileName;
	}
	
	private String chooseDir(String sDirLocation) {

		 String sfileName = null;
		  
		  //JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
		 JFileChooser chooser = new JFileChooser(sDirLocation);
		 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
	      int option = chooser.showOpenDialog(PanelFgSort.this);
	      if(option == JFileChooser.APPROVE_OPTION) {
	    	  txtStatus.setText("You chose "+((chooser.getSelectedFile()!=null)? chooser.getSelectedFile().getAbsoluteFile():"nothing"));
	    	  sfileName = chooser.getSelectedFile().getAbsoluteFile().toString();
	      }
	      if(option == JFileChooser.CANCEL_OPTION) {
	    	  txtStatus.setText("You canceled.");
	       }
		  return sfileName;
	}
	
	public static String stripExtension(final String s)
	{
	    return s != null && s.lastIndexOf(".") > 0 ? s.substring(0, s.lastIndexOf(".")) : s;
	}
	
	
	private void PlcStnNoErrChk() {
		
	    ///only allow for max 3 characters
	    final int iTextFieldMax = 3;
	    txtPlc1StnNo.setDocument(new JTextFieldLimit(iTextFieldMax));
	    txtPlc2StnNo.setDocument(new JTextFieldLimit(iTextFieldMax));
	    txtPlc3StnNo.setDocument(new JTextFieldLimit(iTextFieldMax));
	    txtPlc4StnNo.setDocument(new JTextFieldLimit(iTextFieldMax));
	    
	    ///allow only numeric values to be entered
	    txtPlc1StnNo.addKeyListener(new KeyAdapter() {
	    	  @Override
	    	  public void keyTyped(KeyEvent e) {
	    	    char c = e.getKeyChar();
	    	    if (!Character.isDigit(c)) {
	    	      e.consume(); // Stop the event from propagating.
	    	    }
	    	  }
	    	});
	    
	    ///allow only numeric values to be entered
	    txtPlc2StnNo.addKeyListener(new KeyAdapter() {
	    	  @Override
	    	  public void keyTyped(KeyEvent e) {
	    	    char c = e.getKeyChar();
	    	    if (!Character.isDigit(c)) {
	    	      e.consume(); // Stop the event from propagating.
	    	    }
	    	  }
	    	});
	    
	    ///allow only numeric values to be entered
	    txtPlc3StnNo.addKeyListener(new KeyAdapter() {
	    	  @Override
	    	  public void keyTyped(KeyEvent e) {
	    	    char c = e.getKeyChar();
	    	    if (!Character.isDigit(c)) {
	    	      e.consume(); // Stop the event from propagating.
	    	    }
	    	  }
	    	});
	    
	    ///allow only numeric values to be entered
	    txtPlc4StnNo.addKeyListener(new KeyAdapter() {
	    	  @Override
	    	  public void keyTyped(KeyEvent e) {
	    	    char c = e.getKeyChar();
	    	    if (!Character.isDigit(c)) {
	    	      e.consume(); // Stop the event from propagating.
	    	    }
	    	  }
	    	});
	    
	    
		txtPlc1StnNo.addFocusListener(new FocusAdapter() {
			public void focusLost(FocusEvent arg0) {
				if(txtPlc1StnNo.getText().length() == 1) {
					txtPlc1StnNo.setText("00" + txtPlc1StnNo.getText());
				}
				else 
					if(txtPlc1StnNo.getText().length() == 2)	{
						txtPlc1StnNo.setText("0" + txtPlc1StnNo.getText());						
					}
			}
		});

		txtPlc2StnNo.addFocusListener(new FocusAdapter() {
			public void focusLost(FocusEvent arg0) {
				if(txtPlc2StnNo.getText().length() == 1) {
					txtPlc2StnNo.setText("00" + txtPlc2StnNo.getText());
				}
				else 
					if(txtPlc2StnNo.getText().length() == 2)	{
						txtPlc2StnNo.setText("0" + txtPlc2StnNo.getText());						
					}
			}
		});

		txtPlc3StnNo.addFocusListener(new FocusAdapter() {
			public void focusLost(FocusEvent arg0) {
				if(txtPlc3StnNo.getText().length() == 1) {
					txtPlc3StnNo.setText("00" + txtPlc3StnNo.getText());
				}
				else 
					if(txtPlc3StnNo.getText().length() == 2)	{
						txtPlc3StnNo.setText("0" + txtPlc3StnNo.getText());						
					}
			}
		});

		txtPlc4StnNo.addFocusListener(new FocusAdapter() {
			public void focusLost(FocusEvent arg0) {
				if(txtPlc4StnNo.getText().length() == 1) {
					txtPlc4StnNo.setText("00" + txtPlc4StnNo.getText());
				}
				else 
					if(txtPlc4StnNo.getText().length() == 2)	{
						txtPlc4StnNo.setText("0" + txtPlc4StnNo.getText());						
					}
			}
		});

	}
}